<!DOCTYPE html>
<html CN>







<head>
	
	
	<link rel="stylesheet" href="/css/allinone.min.css"> 

	
	<!-- Global Site Tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-42863699-1"></script>
	<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());
		gtag('config', 'UA-42863699-1');
	</script>
	

	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />

	<title>kubelet 源码分析：启动流程 | Cizixs Write Here</title>

	<meta name="HandheldFriendly" content="True" />
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
	<meta name="generator" content="hexo">
	<meta name="author" content="Cizixs Wu">
	<meta name="description" content="">

	
	<meta name="keywords" content="">
	

	
	<link rel="shortcut icon" href="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg">
	

	
	<meta name="theme-color" content="#3c484e">
	<meta name="msapplication-TileColor" content="#3c484e">
	

	

	

	<meta property="og:site_name" content="Cizixs Write Here">
	<meta property="og:type" content="article">
	<meta property="og:title" content="kubelet 源码分析：启动流程 | Cizixs Write Here">
	<meta property="og:description" content="">
	<meta property="og:url" content="http://cizixs.com/2017/06/06/kubelet-source-code-analysis-part-1/">

	
	<meta property="article:published_time" content="2017-06-06T00:06:00+08:00"/> 
	<meta property="article:author" content="Cizixs Wu">
	<meta property="article:published_first" content="Cizixs Write Here, /2017/06/06/kubelet-source-code-analysis-part-1/" />
	

	
	
	<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
	

	
	<script src="https://cdn.staticfile.org/highlight.js/9.10.0/highlight.min.js"></script>
	

	
	
<link rel="stylesheet" href="/css/prism-base16-ateliersulphurpool.light.css" type="text/css"></head>
<body class="post-template">
    <div class="site-wrapper">
        




<header class="site-header outer" style="z-index: 999">
    <div class="inner">
        
<nav class="site-nav"> 
    <div class="site-nav-left">
        <ul class="nav">
            <li>
                
                <a href="/" title="Home">Home</a>
                
            </li>
            
            
            <li>
                <a href="/about" title="About">About</a>
            </li>
            
            <li>
                <a href="/archives" title="Archives">Archives</a>
            </li>
            
            
        </ul> 
    </div>
    <div class="site-nav-right">
        
<div class="social-links" >
    
    <a class="social-link" title="weibo" href="https://weibo.com/1921727853" target="_blank" rel="noopener">
        <svg viewBox="0 0 1141 1024" xmlns="http://www.w3.org/2000/svg"><path d="M916.48 518.144q27.648 21.504 38.912 51.712t9.216 62.976-14.336 65.536-31.744 59.392q-34.816 48.128-78.848 81.92t-91.136 56.32-94.72 35.328-89.6 18.944-75.264 7.68-51.712 1.536-49.152-2.56-68.096-10.24-78.336-21.504-79.872-36.352-74.24-55.296-59.904-78.848q-16.384-29.696-22.016-63.488t-5.632-86.016q0-22.528 7.68-51.2t27.136-63.488 53.248-75.776 86.016-90.112q51.2-48.128 105.984-85.504t117.248-57.856q28.672-10.24 63.488-11.264t57.344 11.264q10.24 11.264 19.456 23.04t12.288 29.184q3.072 14.336 0.512 27.648t-5.632 26.624-5.12 25.6 2.048 22.528q17.408 2.048 33.792-1.536t31.744-9.216 31.232-11.776 33.28-9.216q27.648-5.12 54.784-4.608t49.152 7.68 36.352 22.016 17.408 38.4q2.048 14.336-2.048 26.624t-8.704 23.04-7.168 22.016 1.536 23.552q3.072 7.168 14.848 13.312t27.136 12.288 32.256 13.312 29.184 16.384zM658.432 836.608q26.624-16.384 53.76-45.056t44.032-64 18.944-75.776-20.48-81.408q-19.456-33.792-47.616-57.344t-62.976-37.376-74.24-19.968-80.384-6.144q-78.848 0-139.776 16.384t-105.472 43.008-72.192 60.416-38.912 68.608q-11.264 33.792-6.656 67.072t20.992 62.976 42.496 53.248 57.856 37.888q58.368 25.6 119.296 32.256t116.224 0.512 100.864-21.504 74.24-33.792zM524.288 513.024q20.48 8.192 38.912 18.432t32.768 27.648q10.24 12.288 17.92 30.72t10.752 39.424 1.536 42.496-9.728 38.912q-8.192 18.432-19.968 37.376t-28.672 35.328-40.448 29.184-57.344 18.944q-61.44 11.264-117.76-11.264t-88.064-74.752q-12.288-39.936-13.312-70.656t16.384-66.56q13.312-27.648 40.448-51.712t62.464-38.912 75.264-17.408 78.848 12.8zM361.472 764.928q37.888 3.072 57.856-18.432t21.504-48.128-15.36-47.616-52.736-16.896q-27.648 3.072-43.008 23.552t-17.408 43.52 9.728 42.496 39.424 21.504zM780.288 6.144q74.752 0 139.776 19.968t113.664 57.856 76.288 92.16 27.648 122.88q0 33.792-16.384 50.688t-35.328 17.408-35.328-14.336-16.384-45.568q0-40.96-22.528-77.824t-59.392-64.512-84.48-43.52-96.768-15.872q-31.744 0-47.104-15.36t-14.336-34.304 18.944-34.304 51.712-15.36zM780.288 169.984q95.232 0 144.384 48.64t49.152 146.944q0 30.72-10.24 43.52t-22.528 11.264-22.528-14.848-10.24-35.84q0-60.416-34.816-96.256t-93.184-35.84q-19.456 0-28.672-10.752t-9.216-23.04 9.728-23.04 28.16-10.752z" /></svg>
    </a>
    

    
    <a class="social-link" title="github" href="https://github.com/cizixs" target="_blank" rel="noopener">
        <svg viewBox="0 0 1049 1024" xmlns="http://www.w3.org/2000/svg"><path d="M524.979332 0C234.676191 0 0 234.676191 0 524.979332c0 232.068678 150.366597 428.501342 358.967656 498.035028 26.075132 5.215026 35.636014-11.299224 35.636014-25.205961 0-12.168395-0.869171-53.888607-0.869171-97.347161-146.020741 31.290159-176.441729-62.580318-176.441729-62.580318-23.467619-60.841976-58.234462-76.487055-58.234463-76.487055-47.804409-32.15933 3.476684-32.15933 3.476685-32.15933 53.019436 3.476684 80.83291 53.888607 80.83291 53.888607 46.935238 79.963739 122.553122 57.365291 152.97411 43.458554 4.345855-33.897672 18.252593-57.365291 33.028501-70.402857-116.468925-12.168395-239.022047-57.365291-239.022047-259.012982 0-57.365291 20.860106-104.300529 53.888607-140.805715-5.215026-13.037566-23.467619-66.926173 5.215027-139.067372 0 0 44.327725-13.906737 144.282399 53.888607 41.720212-11.299224 86.917108-17.383422 131.244833-17.383422s89.524621 6.084198 131.244833 17.383422C756.178839 203.386032 800.506564 217.29277 800.506564 217.29277c28.682646 72.1412 10.430053 126.029806 5.215026 139.067372 33.897672 36.505185 53.888607 83.440424 53.888607 140.805715 0 201.64769-122.553122 245.975415-239.891218 259.012982 19.121764 16.514251 35.636014 47.804409 35.636015 97.347161 0 70.402857-0.869171 126.898978-0.869172 144.282399 0 13.906737 9.560882 30.420988 35.636015 25.205961 208.601059-69.533686 358.967656-265.96635 358.967655-498.035028C1049.958663 234.676191 814.413301 0 524.979332 0z" /></svg>
    </a>
    

    
    <a class="social-link" title="stackoverflow" href="https://stackoverflow.com/users/1925083/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15 21h-10v-2h10v2zm6-11.665l-1.621-9.335-1.993.346 1.62 9.335 1.994-.346zm-5.964 6.937l-9.746-.975-.186 2.016 9.755.879.177-1.92zm.538-2.587l-9.276-2.608-.526 1.954 9.306 2.5.496-1.846zm1.204-2.413l-8.297-4.864-1.029 1.743 8.298 4.865 1.028-1.744zm1.866-1.467l-5.339-7.829-1.672 1.14 5.339 7.829 1.672-1.14zm-2.644 4.195v8h-12v-8h-2v10h16v-10h-2z"/></svg>
    </a>
    

    

    
    <a class="social-link" title="twitter" href="https://twitter.com/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"/></svg>

    </a>
    

    
    <a class="social-link" title="instagram" href="https://www.instagram.com/cizixs/" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
    </a>
    
    
    
</div>
    </div>
</nav>
    </div>
</header>


<main id="site-main" class="site-main outer" role="main">
    <div class="inner">
        <header class="post-full-header">
            <section class="post-full-meta">
                <time  class="post-full-meta-date" datetime="2017-06-05T16:00:00.000Z" itemprop="datePublished">
                    2017-06-6
                </time>
                
                <span class="date-divider">/</span>
                
                <a href="/categories/blog/">blog</a>&nbsp;&nbsp;
                
                
            </section>
            <h1 class="post-full-title">kubelet 源码分析：启动流程</h1>
        </header>
        <article class="post-full no-image">
            
            <section class="post-full-content">
                <div id="lightgallery" class="markdown-body">
                    <h2 id="kubelet-简介"><a href="#kubelet-简介" class="headerlink" title="kubelet 简介"></a>kubelet 简介</h2><p>我在<a href="http://cizixs.com/2016/10/25/kubernetes-intro-kubelet">之前的文章介绍过 kubelet 的功能</a>，简言之，kubelet 保证它所在节点的 pod 能够正常工作。它的核心工作是监听 apiserver，一旦发现当前节点的 pod 配置发生变化，就根据最新的配置执行响应的动作，保证运行的 pod 状态和期望的一致。</p>
<p>kubelet 除了这个最核心的功能之外，还有很多其他特性：</p>
<ul>
<li>定时汇报当前节点的状态给 apiserver，以供调度的时候使用</li>
<li>镜像和容器的清理工作，保证节点上镜像不会占满磁盘空间，退出的容器不会占用太多资源</li>
<li>运行 HTTP Server，对外提供节点和 pod 信息，如果在 debug 模式下，还包括调试信息</li>
<li>……</li>
</ul>
<p>从这篇文章开始，我们深入到 kubelet 的源码中，看它具体的实现原理。</p>
<p><strong>NOTE</strong>：文章采用的 kubernetes 的版本是 <code>v1.5.0</code>，其他版本会有出入，请注意。因为 kubernetes 代码很繁杂，文章会适当删减，保证可读性。删除的内容包括但是不限于：</p>
<ul>
<li>注释、TODO 等信息</li>
<li>alpha 或者实验性特性代码</li>
<li>日志相关代码</li>
<li>参数验证、错误处理</li>
<li>和当前函数或者方法相关性很低的代码</li>
</ul>
<h2 id="KubeletServer-配置对象"><a href="#KubeletServer-配置对象" class="headerlink" title="KubeletServer 配置对象"></a>KubeletServer 配置对象</h2><p>和其他 kubernetes 组件源代码一样，<code>kubelet</code> 的 <code>main</code> 函数入口放在 <code>cmd/</code> 文件夹下：</p>
<pre><code>➜  kubernetes git:(v1.5.0) tree cmd/kubelet 
cmd/kubelet
├── app
│   ├── auth.go
│   ├── bootstrap.go
│   ├── bootstrap_test.go
│   ├── options
│   │   └── options.go
│   ├── plugins.go
│   ├── server.go
│   ├── server_linux.go
│   ├── server_test.go
│   └── server_unsupported.go
└── kubelet.go
</code></pre><p><code>cmd</code> 是所有 kubernetes 组件的入口，主要负责二进制文件的命令行解析，和配置初始化工作，最终还是会调用 <code>pkg/</code> 下面各个组件的内容。对于 <code>kubelet</code> 来说，上面 <code>cmd/kubelet/kubelet.go</code> 就是 <code>main</code> 函数所在的文件，因为它的内容比较简单，所以就全部贴在这里了：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    runtime<span class="token punctuation">.</span><span class="token function">GOMAXPROCS</span><span class="token punctuation">(</span>runtime<span class="token punctuation">.</span><span class="token function">NumCPU</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment" spellcheck="true">// 注意这里，定义了 KubeletServer，主要用于一些参数的初始化和参数的定义</span>
    s <span class="token operator">:=</span> options<span class="token punctuation">.</span><span class="token function">NewKubeletServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    s<span class="token punctuation">.</span><span class="token function">AddFlags</span><span class="token punctuation">(</span>pflag<span class="token punctuation">.</span>CommandLine<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 解析命令行参数</span>
    flag<span class="token punctuation">.</span><span class="token function">InitFlags</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    util<span class="token punctuation">.</span><span class="token function">InitLogs</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">defer</span> util<span class="token punctuation">.</span><span class="token function">FlushLogs</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    verflag<span class="token punctuation">.</span><span class="token function">PrintAndExitIfRequested</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 执行 `app.Run`，运行</span>
    <span class="token keyword">if</span> err <span class="token operator">:=</span> app<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        fmt<span class="token punctuation">.</span><span class="token function">Fprintf</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span>Stderr<span class="token punctuation">,</span> <span class="token string">"%v\n"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
        os<span class="token punctuation">.</span><span class="token function">Exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>这段代码主要分成三个部分，按照顺序运行的：</p>
<ol>
<li>创建一个 <code>KubeletServer</code> 对象，这个对象保存着 kubelet 运行需要的所有配置信息</li>
<li>解析命令行，根据命令行的参数更新 <code>KubeletServer</code></li>
<li>根据 <code>KubeletServer</code> 的配置运行真正的 kubelet 程序</li>
</ol>
<p>NOTE：第二部分是 <code>flag</code> 这个库自动完成的，因此我们只分析其他两个部分。</p>
<p><code>options.NewKubeletServer()</code> 定义在 <code>app/options/options.go</code> 文件中，就是创建一个管理配置的结构体 <code>KubeletServer</code>，初始化一些配置信息。不要被 <code>KubeletServer</code> 这个名字迷惑，它只是一个包含了所有 kubelet 配置参数的结构体，并不是真正运行的 kubelet 实例。<code>KubeletServer</code> 对象结构是这样的：</p>
<pre class=" language-go"><code class="language-go"><span class="token comment" spellcheck="true">// KubeletServer 封装了运行 kubelet 需要的所有参数</span>
<span class="token keyword">type</span> KubeletServer <span class="token keyword">struct</span> <span class="token punctuation">{</span>

    <span class="token comment" spellcheck="true">// 主要的配置结构体，定义在 `apis/componentconfig/types.go` 文件中，包含了命令行所有可以配置的参数。</span>
    <span class="token comment" spellcheck="true">// 因为这个字段是直接引用，所以用户可以通过 `KubeletServer` 直接访问它的字段</span>
    componentconfig<span class="token punctuation">.</span>KubeletConfiguration

    <span class="token comment" spellcheck="true">// kubeconfig 文件的路径，用于访问 apiserver，在后面的版本中这将成为访问 apiserver 的标准方式</span>
    KubeConfig          flag<span class="token punctuation">.</span>StringFlag
    BootstrapKubeconfig <span class="token builtin">string</span>

    <span class="token comment" spellcheck="true">// 如果设置为 true，那么错误的 kubeConfig 配置会直接导致 kubelet 退出</span>
    RequireKubeConfig <span class="token builtin">bool</span>
    <span class="token comment" spellcheck="true">// 之前访问 apiserver 的方式，以后会被上面提到的 kubeConfig 配置取代</span>
    AuthPath          flag<span class="token punctuation">.</span>StringFlag <span class="token comment" spellcheck="true">// Deprecated -- use KubeConfig instead</span>
    APIServerList     <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span>        <span class="token comment" spellcheck="true">// Deprecated -- use KubeConfig instead</span>
    <span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre>
<p><code>KubeletServer</code> 有一个 <code>AddFlags</code> 的方法，它的唯一作用就是把命令行参数和它的字段一一对应起来。这样解析命令行参数的时候，就更新对应的字段。这里是所有命令行参数定义的地方，如果要查询某个版本提供了哪些命令行，我会阅读这部分内容。</p>
<p>后面所有的事情都是在 <code>app.Run()</code> 中做的，看名字也能猜出来，它会运行实际的 kubelet。这个方法定义在 <code>cmd/kubelet/app/server.go</code>：</p>
<pre class=" language-go"><code class="language-go"><span class="token comment" spellcheck="true">// 根据传进来的 kubeDeps 和 KubeletServer，运行 kubelet 的服务，这个方法会一直运行，正常情况下不会返回</span>
<span class="token keyword">func</span> <span class="token function">Run</span><span class="token punctuation">(</span>s <span class="token operator">*</span>options<span class="token punctuation">.</span>KubeletServer<span class="token punctuation">,</span> kubeDeps <span class="token operator">*</span>kubelet<span class="token punctuation">.</span>KubeletDeps<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">run</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"failed to run Kubelet: %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">run</span><span class="token punctuation">(</span>s <span class="token operator">*</span>options<span class="token punctuation">.</span>KubeletServer<span class="token punctuation">,</span> kubeDeps <span class="token operator">*</span>kubelet<span class="token punctuation">.</span>KubeletDeps<span class="token punctuation">)</span> <span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span><span class="token operator">...</span>
    <span class="token keyword">if</span> kubeDeps <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">var</span> kubeClient<span class="token punctuation">,</span> eventClient <span class="token operator">*</span>clientset<span class="token punctuation">.</span>Clientset
        <span class="token keyword">var</span> cloud cloudprovider<span class="token punctuation">.</span>Interface

        <span class="token operator">...</span><span class="token operator">...</span>

        <span class="token comment" spellcheck="true">// 创建出来两个 client：kubeClient 和 eventClient，用来和 apiserver 通信</span>
        clientConfig<span class="token punctuation">,</span> err <span class="token operator">:=</span> <span class="token function">CreateAPIServerClientConfig</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        <span class="token keyword">if</span> err <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            kubeClient<span class="token punctuation">,</span> err <span class="token operator">=</span> clientset<span class="token punctuation">.</span><span class="token function">NewForConfig</span><span class="token punctuation">(</span>clientConfig<span class="token punctuation">)</span>
            <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
                glog<span class="token punctuation">.</span><span class="token function">Warningf</span><span class="token punctuation">(</span><span class="token string">"New kubeClient from clientConfig error: %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
            <span class="token punctuation">}</span>
            <span class="token comment" spellcheck="true">// make a separate client for events</span>
            eventClientConfig <span class="token operator">:=</span> <span class="token operator">*</span>clientConfig
            eventClientConfig<span class="token punctuation">.</span>QPS <span class="token operator">=</span> <span class="token function">float32</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>EventRecordQPS<span class="token punctuation">)</span>
            eventClientConfig<span class="token punctuation">.</span>Burst <span class="token operator">=</span> <span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>EventBurst<span class="token punctuation">)</span>
            eventClient<span class="token punctuation">,</span> err <span class="token operator">=</span> clientset<span class="token punctuation">.</span><span class="token function">NewForConfig</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>eventClientConfig<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        <span class="token operator">...</span><span class="token operator">...</span>

        <span class="token comment" spellcheck="true">// 创建出来一个默认的 kubeDeps，里面包含了 dockerClient、Network Plugins 对象、Volume Plugins 对象</span>
        kubeDeps<span class="token punctuation">,</span> err <span class="token operator">=</span> <span class="token function">UnsecuredKubeletDeps</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> err
        <span class="token punctuation">}</span>
        <span class="token comment" spellcheck="true">// 把之前创建的对象赋给 kubeDeps</span>
        kubeDeps<span class="token punctuation">.</span>Cloud <span class="token operator">=</span> cloud
        kubeDeps<span class="token punctuation">.</span>KubeClient <span class="token operator">=</span> kubeClient
        kubeDeps<span class="token punctuation">.</span>EventClient <span class="token operator">=</span> eventClient
    <span class="token punctuation">}</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// 创建 cAdvisor 对象，负责收集容器的监控信息</span>
    <span class="token keyword">if</span> kubeDeps<span class="token punctuation">.</span>CAdvisorInterface <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        kubeDeps<span class="token punctuation">.</span>CAdvisorInterface<span class="token punctuation">,</span> err <span class="token operator">=</span> cadvisor<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token function">uint</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>CAdvisorPort<span class="token punctuation">)</span><span class="token punctuation">,</span> s<span class="token punctuation">.</span>ContainerRuntime<span class="token punctuation">,</span> s<span class="token punctuation">.</span>RootDirectory<span class="token punctuation">)</span>
        <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> err
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 创建 ContainerManager 对象</span>
    <span class="token keyword">if</span> kubeDeps<span class="token punctuation">.</span>ContainerManager <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token operator">...</span><span class="token operator">...</span>
        kubeDeps<span class="token punctuation">.</span>ContainerManager<span class="token punctuation">,</span> err <span class="token operator">=</span> cm<span class="token punctuation">.</span><span class="token function">NewContainerManager</span><span class="token punctuation">(</span>
            kubeDeps<span class="token punctuation">.</span>Mounter<span class="token punctuation">,</span>
            kubeDeps<span class="token punctuation">.</span>CAdvisorInterface<span class="token punctuation">,</span>
            cm<span class="token punctuation">.</span>NodeConfig<span class="token punctuation">{</span>
                RuntimeCgroupsName<span class="token punctuation">:</span>    s<span class="token punctuation">.</span>RuntimeCgroups<span class="token punctuation">,</span>
                SystemCgroupsName<span class="token punctuation">:</span>     s<span class="token punctuation">.</span>SystemCgroups<span class="token punctuation">,</span>
                KubeletCgroupsName<span class="token punctuation">:</span>    s<span class="token punctuation">.</span>KubeletCgroups<span class="token punctuation">,</span>
                ContainerRuntime<span class="token punctuation">:</span>      s<span class="token punctuation">.</span>ContainerRuntime<span class="token punctuation">,</span>
                CgroupsPerQOS<span class="token punctuation">:</span>         s<span class="token punctuation">.</span>ExperimentalCgroupsPerQOS<span class="token punctuation">,</span>
                CgroupRoot<span class="token punctuation">:</span>            s<span class="token punctuation">.</span>CgroupRoot<span class="token punctuation">,</span>
                CgroupDriver<span class="token punctuation">:</span>          s<span class="token punctuation">.</span>CgroupDriver<span class="token punctuation">,</span>
                ProtectKernelDefaults<span class="token punctuation">:</span> s<span class="token punctuation">.</span>ProtectKernelDefaults<span class="token punctuation">,</span>
                EnableCRI<span class="token punctuation">:</span>             s<span class="token punctuation">.</span>EnableCRI<span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            s<span class="token punctuation">.</span>ExperimentalFailSwapOn<span class="token punctuation">)</span>

        <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> err
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// 运行 kubelet，这个函数会启动 goroutine 一直运行，是 kubelet 核心功能执行的地方</span>
    <span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">RunKubelet</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>s<span class="token punctuation">.</span>KubeletConfiguration<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">,</span> s<span class="token punctuation">.</span>RunOnce<span class="token punctuation">,</span> standaloneMode<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> err
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 运行 healthz HTTP 服务</span>
    <span class="token keyword">if</span> s<span class="token punctuation">.</span>HealthzPort <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">{</span>
        healthz<span class="token punctuation">.</span><span class="token function">DefaultHealthz</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            err <span class="token operator">:=</span> http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span>net<span class="token punctuation">.</span><span class="token function">JoinHostPort</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>HealthzBindAddress<span class="token punctuation">,</span> strconv<span class="token punctuation">.</span><span class="token function">Itoa</span><span class="token punctuation">(</span><span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>HealthzPort<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
            <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
                glog<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Starting health server failed: %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token operator">&lt;-</span>done
    <span class="token keyword">return</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>
</code></pre>
<p>这段代码的最后，是真正运行的东西。前面大部分的内容都是是在创建和初始化 <code>kubeDeps</code> 这个对象，它最终会传递到 <code>RunKubelet</code> 函数中。</p>
<p><code>kubeDeps</code> 的名字听起来很奇怪，其实它内部保存了 kubelet 各个重要组件的对象，之所以要把它作为参数传递，是为了实现 dependency injection。简单地说，就是把 kubelet 依赖的组件对象作为参数传进来，这样可以控制 kubelet 的行为。比如在测试的时候，只要构建 fake 的组件实现，就能很轻松进行测试。<code>KubeDeps</code> 包含的组件很多，下面列出一些：</p>
<ul>
<li>CAdvisorInterface：提供 cAdvisor 接口功能的组件，用来获取监控信息</li>
<li>DockerClient：docker 客户端，用来和 docker 交互</li>
<li>KubeClient：apiserver 客户端，用来和 api server 通信</li>
<li>Mounter：执行 mount 相关操作</li>
<li>NetworkPlugins：网络插件，执行网络设置工作</li>
<li>VolumePlugins：volume 插件，执行 volume 设置工作</li>
</ul>
<p>可以看到，这些组件要么需要和第三方交互（kubeClient、DockerClient），要么有副作用（ <code>Mounter</code>、<code>NetworkPlugins</code>、<code>VolumePlugins</code>），在进行单元测试的时候一般都会编写对应的 Fake 对象，只要满足响应的接口，就能正常工作。</p>
<p><code>run</code> 方法允许传进来的 <code>kubeDeps</code> 为空，这个时候它会自动生成默认的 <code>kubeDeps</code> 对象，这也就是我们上面代码的逻辑。运行 HTTP Server 的代码我们暂时略过，留作以后再讲，继续来看 <code>RunKubelet</code>，它的代码是这样的：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">RunKubelet</span><span class="token punctuation">(</span>kubeCfg <span class="token operator">*</span>componentconfig<span class="token punctuation">.</span>KubeletConfiguration<span class="token punctuation">,</span> kubeDeps <span class="token operator">*</span>kubelet<span class="token punctuation">.</span>KubeletDeps<span class="token punctuation">,</span> runOnce <span class="token builtin">bool</span><span class="token punctuation">,</span> standaloneMode <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// 一些初始化的工作，配置 eventBroadcaster，这样就能发送事件了</span>
    eventBroadcaster <span class="token operator">:=</span> record<span class="token punctuation">.</span><span class="token function">NewBroadcaster</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    kubeDeps<span class="token punctuation">.</span>Recorder <span class="token operator">=</span> eventBroadcaster<span class="token punctuation">.</span><span class="token function">NewRecorder</span><span class="token punctuation">(</span>api<span class="token punctuation">.</span>EventSource<span class="token punctuation">{</span>Component<span class="token punctuation">:</span> <span class="token string">"kubelet"</span><span class="token punctuation">,</span> Host<span class="token punctuation">:</span> <span class="token function">string</span><span class="token punctuation">(</span>nodeName<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    eventBroadcaster<span class="token punctuation">.</span><span class="token function">StartLogging</span><span class="token punctuation">(</span>glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Infof<span class="token punctuation">)</span>
    <span class="token keyword">if</span> kubeDeps<span class="token punctuation">.</span>EventClient <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"Sending events to api server."</span><span class="token punctuation">)</span>
        eventBroadcaster<span class="token punctuation">.</span><span class="token function">StartRecordingToSink</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>unversionedcore<span class="token punctuation">.</span>EventSinkImpl<span class="token punctuation">{</span>Interface<span class="token punctuation">:</span> kubeDeps<span class="token punctuation">.</span>EventClient<span class="token punctuation">.</span><span class="token function">Events</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        glog<span class="token punctuation">.</span><span class="token function">Warning</span><span class="token punctuation">(</span><span class="token string">"No api server defined - no events will be sent to API server."</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    privilegedSources <span class="token operator">:=</span> capabilities<span class="token punctuation">.</span>PrivilegedSources<span class="token punctuation">{</span>
        HostNetworkSources<span class="token punctuation">:</span> hostNetworkSources<span class="token punctuation">,</span>
        HostPIDSources<span class="token punctuation">:</span>     hostPIDSources<span class="token punctuation">,</span>
        HostIPCSources<span class="token punctuation">:</span>     hostIPCSources<span class="token punctuation">,</span>
    <span class="token punctuation">}</span>
    capabilities<span class="token punctuation">.</span><span class="token function">Setup</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>AllowPrivileged<span class="token punctuation">,</span> privilegedSources<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// 使用 Builder 创建 mainKubelet，默认使用 `CreateAndInitKubelet`</span>
    builder <span class="token operator">:=</span> kubeDeps<span class="token punctuation">.</span>Builder
    <span class="token keyword">if</span> builder <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        builder <span class="token operator">=</span> CreateAndInitKubelet
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> kubeDeps<span class="token punctuation">.</span>OSInterface <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        kubeDeps<span class="token punctuation">.</span>OSInterface <span class="token operator">=</span> kubecontainer<span class="token punctuation">.</span>RealOS<span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    k<span class="token punctuation">,</span> err <span class="token operator">:=</span> <span class="token function">builder</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">,</span> standaloneMode<span class="token punctuation">)</span>

    <span class="token operator">...</span><span class="token operator">...</span>
    <span class="token comment" spellcheck="true">// 运行 kubelet</span>
    <span class="token keyword">if</span> runOnce <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> k<span class="token punctuation">.</span><span class="token function">RunOnce</span><span class="token punctuation">(</span>podCfg<span class="token punctuation">.</span><span class="token function">Updates</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"runonce failed: %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        glog<span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"Started kubelet %s as runonce"</span><span class="token punctuation">,</span> version<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        err <span class="token operator">:=</span> <span class="token function">startKubelet</span><span class="token punctuation">(</span>k<span class="token punctuation">,</span> podCfg<span class="token punctuation">,</span> kubeCfg<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">)</span>
        <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> err
        <span class="token punctuation">}</span>
        glog<span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"Started kubelet %s"</span><span class="token punctuation">,</span> version<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>
</code></pre>
<p><code>RunKubelet()</code> 和 <code>runKubelet()</code> 完成了真正意义上的 <code>kubelet</code> 对象的创建和运行。<code>RunKubelet</code> 用来创建 kubelet、验证参数、以及做一些初始化（事件处理和配置 capabilities 等），<code>runKubelet</code> 负责运行。</p>
<p><code>RunKubelet</code> 的内容可以分成三个部分：</p>
<ol>
<li>初始化各个对象，比如 eventBroadcaster，这样就能给 apiserver 发送 kubelet 的事件</li>
<li>通过 builder 创建出来 <code>Kubelet</code> </li>
<li>根据运行模式，运行 <code>Kubelet</code></li>
</ol>
<p>创建工作是在 <code>k, err := builder(kubeCfg, kubeDeps, standaloneMode)</code> 这句完成的，默认的 <code>builder</code> 是 <code>CreateAndInitKubelet</code>：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">CreateAndInitKubelet</span><span class="token punctuation">(</span>kubeCfg <span class="token operator">*</span>componentconfig<span class="token punctuation">.</span>KubeletConfiguration<span class="token punctuation">,</span> kubeDeps <span class="token operator">*</span>kubelet<span class="token punctuation">.</span>KubeletDeps<span class="token punctuation">,</span> standaloneMode <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>k kubelet<span class="token punctuation">.</span>KubeletBootstrap<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token comment" spellcheck="true">// 调用 pkg/kubelet/kubelet.go 文件创建 MainKubelet 的代码</span>
    k<span class="token punctuation">,</span> err <span class="token operator">=</span> kubelet<span class="token punctuation">.</span><span class="token function">NewMainKubelet</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">,</span> standaloneMode<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    k<span class="token punctuation">.</span><span class="token function">BirthCry</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 启动 GC</span>
    k<span class="token punctuation">.</span><span class="token function">StartGarbageCollection</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token keyword">return</span> k<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>
</code></pre>
<p><code>BirthCry()</code> 只是发送一个事件，宣告 kubelet 已经成功启动；<code>StartGarbageCollection()</code> 正如名字所示，启动 kubelet GC 流程，我们后面会详细解释它的内部实现。接下来，我们先看一下 <code>NewMainKubelet()</code> 的代码，毕竟它是创建出 kubelet 的地方。</p>
<h2 id="kubelet-的创建"><a href="#kubelet-的创建" class="headerlink" title="kubelet 的创建"></a>kubelet 的创建</h2><p><code>MainKubelet</code> 函数定义在 <code>pkg/kubelet/kubelet.go#NewMainKubelet</code>，我们终于从 <code>cmd/kubelet/</code> 分析到 <code>pkg/kubelet/</code> 了。</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">NewMainKubelet</span><span class="token punctuation">(</span>kubeCfg <span class="token operator">*</span>componentconfig<span class="token punctuation">.</span>KubeletConfiguration<span class="token punctuation">,</span> kubeDeps <span class="token operator">*</span>KubeletDeps<span class="token punctuation">,</span> standaloneMode <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>Kubelet<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// PodConfig 非常重要，它是 pod 信息的来源，kubelet 支持文件、URL 和 apiserver 三种渠道，PodConfig 将它们汇聚到一起，通过管道来传递</span>
    <span class="token keyword">if</span> kubeDeps<span class="token punctuation">.</span>PodConfig <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        kubeDeps<span class="token punctuation">.</span>PodConfig<span class="token punctuation">,</span> err <span class="token operator">=</span> <span class="token function">makePodSourceConfig</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">,</span> nodeName<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// exec 处理函数，进入到容器中执行命令的方式。之前使用的是 nsenter 命令行的方式，后来 docker 提供了 `docker exec` 命令，默认是后者</span>
    <span class="token keyword">var</span> dockerExecHandler dockertools<span class="token punctuation">.</span>ExecHandler
    <span class="token keyword">switch</span> kubeCfg<span class="token punctuation">.</span>DockerExecHandlerName <span class="token punctuation">{</span>
    <span class="token keyword">case</span> <span class="token string">"native"</span><span class="token punctuation">:</span>
        dockerExecHandler <span class="token operator">=</span> <span class="token operator">&amp;</span>dockertools<span class="token punctuation">.</span>NativeExecHandler<span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token keyword">case</span> <span class="token string">"nsenter"</span><span class="token punctuation">:</span>
        dockerExecHandler <span class="token operator">=</span> <span class="token operator">&amp;</span>dockertools<span class="token punctuation">.</span>NsenterExecHandler<span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token keyword">default</span><span class="token punctuation">:</span>
        glog<span class="token punctuation">.</span><span class="token function">Warningf</span><span class="token punctuation">(</span><span class="token string">"Unknown Docker exec handler %q; defaulting to native"</span><span class="token punctuation">,</span> kubeCfg<span class="token punctuation">.</span>DockerExecHandlerName<span class="token punctuation">)</span>
        dockerExecHandler <span class="token operator">=</span> <span class="token operator">&amp;</span>dockertools<span class="token punctuation">.</span>NativeExecHandler<span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 使用 reflector 把 ListWatch 得到的服务信息实时同步到 serviceStore 对象中</span>
    serviceStore <span class="token operator">:=</span> cache<span class="token punctuation">.</span><span class="token function">NewIndexer</span><span class="token punctuation">(</span>cache<span class="token punctuation">.</span>MetaNamespaceKeyFunc<span class="token punctuation">,</span> cache<span class="token punctuation">.</span>Indexers<span class="token punctuation">{</span>cache<span class="token punctuation">.</span>NamespaceIndex<span class="token punctuation">:</span> cache<span class="token punctuation">.</span>MetaNamespaceIndexFunc<span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> kubeClient <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        serviceLW <span class="token operator">:=</span> cache<span class="token punctuation">.</span><span class="token function">NewListWatchFromClient</span><span class="token punctuation">(</span>kubeClient<span class="token punctuation">.</span><span class="token function">Core</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">RESTClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"services"</span><span class="token punctuation">,</span> api<span class="token punctuation">.</span>NamespaceAll<span class="token punctuation">,</span> fields<span class="token punctuation">.</span><span class="token function">Everything</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        cache<span class="token punctuation">.</span><span class="token function">NewReflector</span><span class="token punctuation">(</span>serviceLW<span class="token punctuation">,</span> <span class="token operator">&amp;</span>api<span class="token punctuation">.</span>Service<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> serviceStore<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    serviceLister <span class="token operator">:=</span> <span class="token operator">&amp;</span>cache<span class="token punctuation">.</span>StoreToServiceLister<span class="token punctuation">{</span>Indexer<span class="token punctuation">:</span> serviceStore<span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 使用 reflector 把 ListWatch 得到的节点信息实时同步到  nodeStore 对象中</span>
    nodeStore <span class="token operator">:=</span> cache<span class="token punctuation">.</span><span class="token function">NewStore</span><span class="token punctuation">(</span>cache<span class="token punctuation">.</span>MetaNamespaceKeyFunc<span class="token punctuation">)</span>
    <span class="token keyword">if</span> kubeClient <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        fieldSelector <span class="token operator">:=</span> fields<span class="token punctuation">.</span>Set<span class="token punctuation">{</span>api<span class="token punctuation">.</span>ObjectNameField<span class="token punctuation">:</span> <span class="token function">string</span><span class="token punctuation">(</span>nodeName<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">AsSelector</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        nodeLW <span class="token operator">:=</span> cache<span class="token punctuation">.</span><span class="token function">NewListWatchFromClient</span><span class="token punctuation">(</span>kubeClient<span class="token punctuation">.</span><span class="token function">Core</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">RESTClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"nodes"</span><span class="token punctuation">,</span> api<span class="token punctuation">.</span>NamespaceAll<span class="token punctuation">,</span> fieldSelector<span class="token punctuation">)</span>
        cache<span class="token punctuation">.</span><span class="token function">NewReflector</span><span class="token punctuation">(</span>nodeLW<span class="token punctuation">,</span> <span class="token operator">&amp;</span>api<span class="token punctuation">.</span>Node<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> nodeStore<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    nodeLister <span class="token operator">:=</span> <span class="token operator">&amp;</span>cache<span class="token punctuation">.</span>StoreToNodeLister<span class="token punctuation">{</span>Store<span class="token punctuation">:</span> nodeStore<span class="token punctuation">}</span>
    nodeInfo <span class="token operator">:=</span> <span class="token operator">&amp;</span>predicates<span class="token punctuation">.</span>CachedNodeInfo<span class="token punctuation">{</span>StoreToNodeLister<span class="token punctuation">:</span> nodeLister<span class="token punctuation">}</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// 根据配置信息和各种对象创建 Kubelet 实例</span>
    klet <span class="token operator">:=</span> <span class="token operator">&amp;</span>Kubelet<span class="token punctuation">{</span>
        hostname<span class="token punctuation">:</span>                       hostname<span class="token punctuation">,</span>
        nodeName<span class="token punctuation">:</span>                       nodeName<span class="token punctuation">,</span>
        dockerClient<span class="token punctuation">:</span>                   kubeDeps<span class="token punctuation">.</span>DockerClient<span class="token punctuation">,</span>
        kubeClient<span class="token punctuation">:</span>                     kubeClient<span class="token punctuation">,</span>
        <span class="token operator">...</span><span class="token operator">...</span>
        clusterDomain<span class="token punctuation">:</span>                  kubeCfg<span class="token punctuation">.</span>ClusterDomain<span class="token punctuation">,</span>
        clusterDNS<span class="token punctuation">:</span>                     net<span class="token punctuation">.</span><span class="token function">ParseIP</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>ClusterDNS<span class="token punctuation">)</span><span class="token punctuation">,</span>
        serviceLister<span class="token punctuation">:</span>                  serviceLister<span class="token punctuation">,</span>
        nodeLister<span class="token punctuation">:</span>                     nodeLister<span class="token punctuation">,</span>
        nodeInfo<span class="token punctuation">:</span>                       nodeInfo<span class="token punctuation">,</span>
        masterServiceNamespace<span class="token punctuation">:</span>         kubeCfg<span class="token punctuation">.</span>MasterServiceNamespace<span class="token punctuation">,</span>
        streamingConnectionIdleTimeout<span class="token punctuation">:</span> kubeCfg<span class="token punctuation">.</span>StreamingConnectionIdleTimeout<span class="token punctuation">.</span>Duration<span class="token punctuation">,</span>
        recorder<span class="token punctuation">:</span>                       kubeDeps<span class="token punctuation">.</span>Recorder<span class="token punctuation">,</span>
        cadvisor<span class="token punctuation">:</span>                       kubeDeps<span class="token punctuation">.</span>CAdvisorInterface<span class="token punctuation">,</span>
        diskSpaceManager<span class="token punctuation">:</span>               diskSpaceManager<span class="token punctuation">,</span>
        <span class="token operator">...</span><span class="token operator">...</span>
    <span class="token punctuation">}</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// 网络插件的初始化工作</span>
    <span class="token keyword">if</span> plug<span class="token punctuation">,</span> err <span class="token operator">:=</span> network<span class="token punctuation">.</span><span class="token function">InitNetworkPlugin</span><span class="token punctuation">(</span>kubeDeps<span class="token punctuation">.</span>NetworkPlugins<span class="token punctuation">,</span> kubeCfg<span class="token punctuation">.</span>NetworkPluginName<span class="token punctuation">,</span> <span class="token operator">&amp;</span>criNetworkHost<span class="token punctuation">{</span><span class="token operator">&amp;</span>networkHost<span class="token punctuation">{</span>klet<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">,</span> klet<span class="token punctuation">.</span>hairpinMode<span class="token punctuation">,</span> klet<span class="token punctuation">.</span>nonMasqueradeCIDR<span class="token punctuation">,</span> <span class="token function">int</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>NetworkPluginMTU<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        klet<span class="token punctuation">.</span>networkPlugin <span class="token operator">=</span> plug
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 从 cAdvisor 获取当前机器的信息</span>
    machineInfo<span class="token punctuation">,</span> err <span class="token operator">:=</span> klet<span class="token punctuation">.</span><span class="token function">GetCachedMachineInfo</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token operator">...</span><span class="token operator">...</span>

    procFs <span class="token operator">:=</span> procfs<span class="token punctuation">.</span><span class="token function">NewProcFS</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    imageBackOff <span class="token operator">:=</span> flowcontrol<span class="token punctuation">.</span><span class="token function">NewBackOff</span><span class="token punctuation">(</span>backOffPeriod<span class="token punctuation">,</span> MaxContainerBackOff<span class="token punctuation">)</span>

    klet<span class="token punctuation">.</span>livenessManager <span class="token operator">=</span> proberesults<span class="token punctuation">.</span><span class="token function">NewManager</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// podManager 负责管理当前节点上的 pod 信息，它保存了所有 pod 的内容，包括 static pod。</span>
    <span class="token comment" spellcheck="true">// kubelet 从本地文件、网络地址和 apiserver 三个地方获取 pod 的内容，</span>
    klet<span class="token punctuation">.</span>podCache <span class="token operator">=</span> kubecontainer<span class="token punctuation">.</span><span class="token function">NewCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    klet<span class="token punctuation">.</span>podManager <span class="token operator">=</span> kubepod<span class="token punctuation">.</span><span class="token function">NewBasicPodManager</span><span class="token punctuation">(</span>kubepod<span class="token punctuation">.</span><span class="token function">NewBasicMirrorClient</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>kubeClient<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token operator">...</span><span class="token operator">...</span>

    <span class="token comment" spellcheck="true">// 创建 runtime 对象，以后会改用 CRI 接口和 runtime 交互，目前使用 DockerManager</span>
    <span class="token keyword">if</span> kubeCfg<span class="token punctuation">.</span>EnableCRI <span class="token punctuation">{</span>
        <span class="token operator">...</span><span class="token operator">...</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token keyword">switch</span> kubeCfg<span class="token punctuation">.</span>ContainerRuntime <span class="token punctuation">{</span>
        <span class="token keyword">case</span> <span class="token string">"docker"</span><span class="token punctuation">:</span>
            runtime <span class="token operator">:=</span> dockertools<span class="token punctuation">.</span><span class="token function">NewDockerManager</span><span class="token punctuation">(</span>
                kubeDeps<span class="token punctuation">.</span>DockerClient<span class="token punctuation">,</span>
                kubecontainer<span class="token punctuation">.</span><span class="token function">FilterEventRecorder</span><span class="token punctuation">(</span>kubeDeps<span class="token punctuation">.</span>Recorder<span class="token punctuation">)</span><span class="token punctuation">,</span>
                klet<span class="token punctuation">.</span>livenessManager<span class="token punctuation">,</span>
                containerRefManager<span class="token punctuation">,</span>
                klet<span class="token punctuation">.</span>podManager<span class="token punctuation">,</span>
                machineInfo<span class="token punctuation">,</span>
                kubeCfg<span class="token punctuation">.</span>PodInfraContainerImage<span class="token punctuation">,</span>
                <span class="token function">float32</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>RegistryPullQPS<span class="token punctuation">)</span><span class="token punctuation">,</span>
                <span class="token function">int</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>RegistryBurst<span class="token punctuation">)</span><span class="token punctuation">,</span>
                ContainerLogsDir<span class="token punctuation">,</span>
                kubeDeps<span class="token punctuation">.</span>OSInterface<span class="token punctuation">,</span>
                klet<span class="token punctuation">.</span>networkPlugin<span class="token punctuation">,</span>
                klet<span class="token punctuation">,</span>
                klet<span class="token punctuation">.</span>httpClient<span class="token punctuation">,</span>
                dockerExecHandler<span class="token punctuation">,</span>
                kubeDeps<span class="token punctuation">.</span>OOMAdjuster<span class="token punctuation">,</span>
                procFs<span class="token punctuation">,</span>
                klet<span class="token punctuation">.</span>cpuCFSQuota<span class="token punctuation">,</span>
                imageBackOff<span class="token punctuation">,</span>
                kubeCfg<span class="token punctuation">.</span>SerializeImagePulls<span class="token punctuation">,</span>
                kubeCfg<span class="token punctuation">.</span>EnableCustomMetrics<span class="token punctuation">,</span>
                klet<span class="token punctuation">.</span>hairpinMode <span class="token operator">==</span> componentconfig<span class="token punctuation">.</span>HairpinVeth <span class="token operator">&amp;&amp;</span> kubeCfg<span class="token punctuation">.</span>NetworkPluginName <span class="token operator">!=</span> <span class="token string">"kubenet"</span><span class="token punctuation">,</span>
                kubeCfg<span class="token punctuation">.</span>SeccompProfileRoot<span class="token punctuation">,</span>
                kubeDeps<span class="token punctuation">.</span>ContainerRuntimeOptions<span class="token operator">...</span><span class="token punctuation">,</span>
            <span class="token punctuation">)</span>
            klet<span class="token punctuation">.</span>containerRuntime <span class="token operator">=</span> runtime
            klet<span class="token punctuation">.</span>runner <span class="token operator">=</span> kubecontainer<span class="token punctuation">.</span><span class="token function">DirectStreamingRunner</span><span class="token punctuation">(</span>runtime<span class="token punctuation">)</span>
        <span class="token keyword">case</span> <span class="token string">"rkt"</span><span class="token punctuation">:</span>
            <span class="token operator">...</span><span class="token operator">...</span>
        <span class="token keyword">default</span><span class="token punctuation">:</span>
            <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"unsupported container runtime %q specified"</span><span class="token punctuation">,</span> kubeCfg<span class="token punctuation">.</span>ContainerRuntime<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token operator">...</span><span class="token operator">...</span>

    klet<span class="token punctuation">.</span>pleg <span class="token operator">=</span> pleg<span class="token punctuation">.</span><span class="token function">NewGenericPLEG</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>containerRuntime<span class="token punctuation">,</span> plegChannelCapacity<span class="token punctuation">,</span> plegRelistPeriod<span class="token punctuation">,</span> klet<span class="token punctuation">.</span>podCache<span class="token punctuation">,</span> clock<span class="token punctuation">.</span>RealClock<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    klet<span class="token punctuation">.</span>runtimeState <span class="token operator">=</span> <span class="token function">newRuntimeState</span><span class="token punctuation">(</span>maxWaitForContainerRuntime<span class="token punctuation">)</span>
    klet<span class="token punctuation">.</span><span class="token function">updatePodCIDR</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>PodCIDR<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 创建 containerGC 对象，进行周期性的容器清理工作</span>
    containerGC<span class="token punctuation">,</span> err <span class="token operator">:=</span> kubecontainer<span class="token punctuation">.</span><span class="token function">NewContainerGC</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>containerRuntime<span class="token punctuation">,</span> containerGCPolicy<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>
    klet<span class="token punctuation">.</span>containerGC <span class="token operator">=</span> containerGC
    klet<span class="token punctuation">.</span>containerDeletor <span class="token operator">=</span> <span class="token function">newPodContainerDeletor</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>containerRuntime<span class="token punctuation">,</span> integer<span class="token punctuation">.</span><span class="token function">IntMax</span><span class="token punctuation">(</span>containerGCPolicy<span class="token punctuation">.</span>MaxPerPodContainer<span class="token punctuation">,</span> minDeadContainerInPod<span class="token punctuation">)</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 创建 imageManager 对象，管理镜像</span>
    imageManager<span class="token punctuation">,</span> err <span class="token operator">:=</span> images<span class="token punctuation">.</span><span class="token function">NewImageGCManager</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>containerRuntime<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">.</span>CAdvisorInterface<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">.</span>Recorder<span class="token punctuation">,</span> nodeRef<span class="token punctuation">,</span> imageGCPolicy<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"failed to initialize image manager: %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    klet<span class="token punctuation">.</span>imageManager <span class="token operator">=</span> imageManager

    <span class="token comment" spellcheck="true">// statusManager 实时检测节点上 pod 的状态，并更新到 apiserver 对应的 pod </span>
    klet<span class="token punctuation">.</span>statusManager <span class="token operator">=</span> status<span class="token punctuation">.</span><span class="token function">NewManager</span><span class="token punctuation">(</span>kubeClient<span class="token punctuation">,</span> klet<span class="token punctuation">.</span>podManager<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// probeManager 检测 pod 的状态，并通过 statusManager 进行更新</span>
    klet<span class="token punctuation">.</span>probeManager <span class="token operator">=</span> prober<span class="token punctuation">.</span><span class="token function">NewManager</span><span class="token punctuation">(</span>
        klet<span class="token punctuation">.</span>statusManager<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>livenessManager<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>runner<span class="token punctuation">,</span>
        containerRefManager<span class="token punctuation">,</span>
        kubeDeps<span class="token punctuation">.</span>Recorder<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// volumeManager 管理节点上 volume</span>

    klet<span class="token punctuation">.</span>volumePluginMgr<span class="token punctuation">,</span> err <span class="token operator">=</span>
        <span class="token function">NewInitializedVolumePluginMgr</span><span class="token punctuation">(</span>klet<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">.</span>VolumePlugins<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>
    <span class="token operator">...</span><span class="token operator">...</span>
    <span class="token comment" spellcheck="true">// setup volumeManager</span>
    klet<span class="token punctuation">.</span>volumeManager<span class="token punctuation">,</span> err <span class="token operator">=</span> volumemanager<span class="token punctuation">.</span><span class="token function">NewVolumeManager</span><span class="token punctuation">(</span>
        kubeCfg<span class="token punctuation">.</span>EnableControllerAttachDetach<span class="token punctuation">,</span>
        nodeName<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>podManager<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>kubeClient<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>volumePluginMgr<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>containerRuntime<span class="token punctuation">,</span>
        kubeDeps<span class="token punctuation">.</span>Mounter<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span><span class="token function">getPodsDir</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        kubeDeps<span class="token punctuation">.</span>Recorder<span class="token punctuation">,</span>
        kubeCfg<span class="token punctuation">.</span>ExperimentalCheckNodeCapabilitiesBeforeMount<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 保存了节点上正在运行的 pod 信息</span>
    runtimeCache<span class="token punctuation">,</span> err <span class="token operator">:=</span> kubecontainer<span class="token punctuation">.</span><span class="token function">NewRuntimeCache</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>containerRuntime<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>
    klet<span class="token punctuation">.</span>runtimeCache <span class="token operator">=</span> runtimeCache
    klet<span class="token punctuation">.</span>reasonCache <span class="token operator">=</span> <span class="token function">NewReasonCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    klet<span class="token punctuation">.</span>workQueue <span class="token operator">=</span> queue<span class="token punctuation">.</span><span class="token function">NewBasicWorkQueue</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>clock<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// podWorkers 是具体的执行者</span>
    klet<span class="token punctuation">.</span>podWorkers <span class="token operator">=</span> <span class="token function">newPodWorkers</span><span class="token punctuation">(</span>klet<span class="token punctuation">.</span>syncPod<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">.</span>Recorder<span class="token punctuation">,</span> klet<span class="token punctuation">.</span>workQueue<span class="token punctuation">,</span> klet<span class="token punctuation">.</span>resyncInterval<span class="token punctuation">,</span> backOffPeriod<span class="token punctuation">,</span> klet<span class="token punctuation">.</span>podCache<span class="token punctuation">)</span>

    <span class="token operator">...</span><span class="token operator">...</span>
    klet<span class="token punctuation">.</span>kubeletConfiguration <span class="token operator">=</span> <span class="token operator">*</span>kubeCfg
    <span class="token keyword">return</span> klet<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>
</code></pre>
<p><code>NewMainKubelet</code> 正如名字所示，主要的工作就是创建 <code>Kubelet</code> 这个对象，它包含了 kubelet 运行需要的所有对象，上面的代码就是各种对象的初始化和赋值的过程，这里只介绍几个非常重要的对象来说：</p>
<ul>
<li>podConfig：这个对象里面会从文件、网络和 apiserver 三个来源中汇聚节点要运行的 pod 信息，并通过管道发送出来，读取这个管道就能获取实时的 pod 最新配置</li>
<li>ServiceLister：能够读取 kubernetes 中服务信息</li>
<li>nodeLister：能够读取 apiserver 中节点的信息</li>
<li>diskSpaceManager：返回容器存储空间的信息</li>
<li>podManager：缓存了 pod 的信息，是所有需要该信息都会去访问的地方</li>
<li>runtime：容器运行时，对容器引擎（docker 或者 rkt）的一层封装，负责调用容器引擎接口管理容器的状态，比如启动、暂停、杀死容器等</li>
<li>probeManager：如果 pod 配置了状态监测，那么 probeManager 会定时检查 pod 是否正常工作，并通过 statusManager 向 apiserver 更新 pod 的状态</li>
<li>volumeManager：负责容器需要的 volume 管理。检测某个 volume 是否已经 mount、获取 pod 使用的 volume 等</li>
<li>podWorkers：具体的执行者，每次有 pod 需要更新的时候都会发送给它</li>
</ul>
<p>这里并不一一展开所有对象的实现和具体功能，以后的文章会对其中一些继续分析。</p>
<h2 id="kubelet-的运行"><a href="#kubelet-的运行" class="headerlink" title="kubelet 的运行"></a>kubelet 的运行</h2><p>接着回到 kubelet 的分析，通过 <code>NewMainKubelet</code> 创建完 <code>Kubelet</code> 对象，下一步就是看看如果运行它。在 <code>RunKubelet</code> 内部，我们看到它最终会调用 <code>startKublet</code> 函数：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">startKubelet</span><span class="token punctuation">(</span>k kubelet<span class="token punctuation">.</span>KubeletBootstrap<span class="token punctuation">,</span> podCfg <span class="token operator">*</span>config<span class="token punctuation">.</span>PodConfig<span class="token punctuation">,</span> kubeCfg <span class="token operator">*</span>componentconfig<span class="token punctuation">.</span>KubeletConfiguration<span class="token punctuation">,</span> kubeDeps <span class="token operator">*</span>kubelet<span class="token punctuation">.</span>KubeletDeps<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
    <span class="token comment" spellcheck="true">// 启动 kubelet</span>
    <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> k<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>podCfg<span class="token punctuation">.</span><span class="token function">Updates</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 启动 kubelet server</span>
    <span class="token keyword">if</span> kubeCfg<span class="token punctuation">.</span>EnableServer <span class="token punctuation">{</span>
        <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            k<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span>net<span class="token punctuation">.</span><span class="token function">ParseIP</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>Address<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">uint</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>Port<span class="token punctuation">)</span><span class="token punctuation">,</span> kubeDeps<span class="token punctuation">.</span>TLSOptions<span class="token punctuation">,</span> kubeDeps<span class="token punctuation">.</span>Auth<span class="token punctuation">,</span> kubeCfg<span class="token punctuation">.</span>EnableDebuggingHandlers<span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> kubeCfg<span class="token punctuation">.</span>ReadOnlyPort <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">{</span>
        <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            k<span class="token punctuation">.</span><span class="token function">ListenAndServeReadOnly</span><span class="token punctuation">(</span>net<span class="token punctuation">.</span><span class="token function">ParseIP</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>Address<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">uint</span><span class="token punctuation">(</span>kubeCfg<span class="token punctuation">.</span>ReadOnlyPort<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">return</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>
</code></pre>
<p>运行 kubelet 主要启动两个功能，<code>k.Run()</code> 来进入主循环，<code>k.ListenAndServe()</code> 启动 kubelet 的 API 服务，后者并不是这篇文章的重点，我们来看看前者，它的执行入口是 <code>k.Run(podCfg.Updates())</code>，<code>podCfg.Updates()</code> 我们前面已经说过，它是一个管道，会实时地发送过来 pod 最新的配置信息，至于是怎么实现的，我们以后再说，这里知道它的作用就行。<code>Run</code> 方法的代码如下：</p>
<pre class=" language-go"><code class="language-go"><span class="token operator">/</span> Run starts the kubelet reacting to config updates
<span class="token keyword">func</span> <span class="token punctuation">(</span>kl <span class="token operator">*</span>Kubelet<span class="token punctuation">)</span> <span class="token function">Run</span><span class="token punctuation">(</span>updates <span class="token operator">&lt;-</span><span class="token keyword">chan</span> kubetypes<span class="token punctuation">.</span>PodUpdate<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

    <span class="token comment" spellcheck="true">// Start volume manager</span>
    <span class="token keyword">go</span> kl<span class="token punctuation">.</span>volumeManager<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>kl<span class="token punctuation">.</span>sourcesReady<span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 定时向 apiserver 更新 node 信息，用作调度时的重要参考</span>
    <span class="token keyword">if</span> kl<span class="token punctuation">.</span>kubeClient <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token comment" spellcheck="true">// Start syncing node status immediately, this may set up things the runtime needs to run.</span>
        <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span>kl<span class="token punctuation">.</span>syncNodeStatus<span class="token punctuation">,</span> kl<span class="token punctuation">.</span>nodeStatusUpdateFrequency<span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span>kl<span class="token punctuation">.</span>syncNetworkStatus<span class="token punctuation">,</span> <span class="token number">30</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>
    <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span>kl<span class="token punctuation">.</span>updateRuntimeUp<span class="token punctuation">,</span> <span class="token number">5</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// Start loop to sync iptables util rules</span>
    <span class="token keyword">if</span> kl<span class="token punctuation">.</span>makeIPTablesUtilChains <span class="token punctuation">{</span>
        <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span>kl<span class="token punctuation">.</span>syncNetworkUtil<span class="token punctuation">,</span> <span class="token number">1</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Minute<span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 删除 podWorker 没有正常处理的 pod </span>
    <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Until</span><span class="token punctuation">(</span>kl<span class="token punctuation">.</span>podKiller<span class="token punctuation">,</span> <span class="token number">1</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">,</span> wait<span class="token punctuation">.</span>NeverStop<span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// Start component sync loops.</span>
    <span class="token comment" spellcheck="true">// 管理 pod 和容器的状态</span>
    kl<span class="token punctuation">.</span>statusManager<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// readiness 和 liveness 管理</span>
    kl<span class="token punctuation">.</span>probeManager<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// pleg  的全称是 Pod Lifecycle Event Generator</span>
    kl<span class="token punctuation">.</span>pleg<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// 宫殿的入口</span>
    kl<span class="token punctuation">.</span><span class="token function">syncLoop</span><span class="token punctuation">(</span>updates<span class="token punctuation">,</span> kl<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<p>基本上就是 <code>kubelet</code> 各种组件的启动，每个组件都是以 goroutine 运行的，这里不做赘述。最后一句 <code>kl.syncLoop(updates, kl)</code> 是处理所有 pod 更新的主循环，获取 pod 的变化（新建、修改和删除），调用对应的处理函数保证节点上的容器符合 pod 的配置。</p>
<p>如果 kubelet 是做宫殿，那么 <code>syncLoop</code> 就是这座宫殿的入口。我们从很远的地方出发，穿过丛林、越过高山，一路上到处问路，经过一座座的城镇，终于抵达都城。穿行过眼花缭乱的商铺、士兵、民宅，站在金碧辉煌巍峨高大的宫殿门口，心中一定激情澎湃。</p>
<p>在下一篇文章，我们就要打开宫殿大门，一探其中究竟。</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul>
<li><a href="http://www.webpaas.com/index.php/archives/120/" target="_blank" rel="noopener">k8s kubelet源码剖析</a></li>
<li><a href="http://licyhust.com/%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF/2016/10/20/kubelet-1/" target="_blank" rel="noopener">kubelet源码解析(1)</a></li>
<li><a href="http://www.sel.zju.edu.cn/?p=595" target="_blank" rel="noopener">KUBERNETES NODE COMPONENTS – KUBELET</a></li>
<li><a href="http://blog.csdn.net/zhaoguoguang/article/details/51225553" target="_blank" rel="noopener">kubernetes源码分析 – kubelet组件</a></li>
</ul>

                </div>
            </section>
        </article>
    </div>
    
<nav class="pagination">
    
    
    <a class="prev-post" title="kubelet 源码分析：pod 新建流程" href="/2017/06/07/kubelet-source-code-analysis-part-2/">
        ← kubelet 源码分析：pod 新建流程
    </a>
    
    <span class="prev-next-post">•</span>
    
    <a class="next-post" title="CNI：容器网络接口" href="/2017/05/23/container-network-cni/">
        CNI：容器网络接口 →
    </a>
    
    
</nav>

    <div class="inner">
    <!-- Begin Mailchimp Signup Form -->
    <link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
    <style type="text/css">
    	#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
    	/* Add your own Mailchimp form style overrides in your site stylesheet or in this style block.
    	   We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
    </style>
    <div id="mc_embed_signup">
    <form action="https://cizixs.us7.list-manage.com/subscribe/post?u=2d561b8dea52d73a2e05e6dcb&amp;id=5c710f135b" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
        <div id="mc_embed_signup_scroll">
    	<h2>订阅本博客，第一时间收到文章更新</h2>
    <div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
    <div class="mc-field-group">
    	<label for="mce-EMAIL">邮件地址  <span class="asterisk">*</span>
    </label>
    	<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
    </div>
    	<div id="mce-responses" class="clear">
    		<div class="response" id="mce-error-response" style="display:none"></div>
    		<div class="response" id="mce-success-response" style="display:none"></div>
    	</div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
        <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_2d561b8dea52d73a2e05e6dcb_5c710f135b" tabindex="-1" value=""></div>
        <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
        </div>
    </form>
    </div>
    <script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
    <!--End mc_embed_signup-->
    </div>

    <div class="inner">
        <div id="disqus_thread"></div>
    </div>

    
</main>

<div class="t-g-control">
    <div class="gotop">
        <svg class="icon" width="32px" height="32px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M793.024 710.272a32 32 0 1 0 45.952-44.544l-310.304-320a32 32 0 0 0-46.4 0.48l-297.696 320a32 32 0 0 0 46.848 43.584l274.752-295.328 286.848 295.808z" fill="#8a8a8a" /></svg>
    </div>
    <div class="toc-control">
        <svg class="icon toc-icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M779.776 480h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M779.776 672h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M256 288a32 32 0 1 0 0 64 32 32 0 0 0 0-64M392.576 352h387.2a32 32 0 0 0 0-64h-387.2a32 32 0 0 0 0 64M256 480a32 32 0 1 0 0 64 32 32 0 0 0 0-64M256 672a32 32 0 1 0 0 64 32 32 0 0 0 0-64" fill="#8a8a8a" /></svg>
        <svg class="icon toc-close" style="display: none;" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 960c-247.039484 0-448-200.960516-448-448S264.960516 64 512 64 960 264.960516 960 512 759.039484 960 512 960zM512 128.287273c-211.584464 0-383.712727 172.128262-383.712727 383.712727 0 211.551781 172.128262 383.712727 383.712727 383.712727 211.551781 0 383.712727-172.159226 383.712727-383.712727C895.712727 300.415536 723.551781 128.287273 512 128.287273z" fill="#8a8a8a" /><path d="M557.05545 513.376159l138.367639-136.864185c12.576374-12.416396 12.672705-32.671738 0.25631-45.248112s-32.704421-12.672705-45.248112-0.25631l-138.560301 137.024163-136.447897-136.864185c-12.512727-12.512727-32.735385-12.576374-45.248112-0.063647-12.512727 12.480043-12.54369 32.735385-0.063647 45.248112l136.255235 136.671523-137.376804 135.904314c-12.576374 12.447359-12.672705 32.671738-0.25631 45.248112 6.271845 6.335493 14.496116 9.504099 22.751351 9.504099 8.12794 0 16.25588-3.103239 22.496761-9.247789l137.567746-136.064292 138.687596 139.136568c6.240882 6.271845 14.432469 9.407768 22.65674 9.407768 8.191587 0 16.352211-3.135923 22.591372-9.34412 12.512727-12.480043 12.54369-32.704421 0.063647-45.248112L557.05545 513.376159z" fill="#8a8a8a" /></svg>
    </div>
    <div class="gobottom">
        <svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M231.424 346.208a32 32 0 0 0-46.848 43.584l297.696 320a32 32 0 0 0 46.4 0.48l310.304-320a32 32 0 1 0-45.952-44.544l-286.848 295.808-274.752-295.36z" fill="#8a8a8a" /></svg>
    </div>
</div>
<div class="toc-main" style="right: -100%">
    <div class="post-toc">
        <span>TOC</span>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#kubelet-简介"><span class="toc-text">kubelet 简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#KubeletServer-配置对象"><span class="toc-text">KubeletServer 配置对象</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#kubelet-的创建"><span class="toc-text">kubelet 的创建</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#kubelet-的运行"><span class="toc-text">kubelet 的运行</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#参考资料"><span class="toc-text">参考资料</span></a></li></ol>
    </div>
</div>



        

<aside class="read-next outer">
    <div class="inner">
        <div class="read-next-feed">
            
            

<article class="read-next-card"  style="background-image: url(https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxcn9ft3j318w0txdo6.jpg)"  >
  <header class="read-next-card-header">
    <small class="read-next-card-header-sitetitle">&mdash; Cizixs Write Here &mdash;</small>
    <h3 class="read-next-card-header-title">Recent Posts</h3>
  </header>
  <div class="read-next-divider">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M13 14.5s2 3 5 3 5.5-2.463 5.5-5.5S21 6.5 18 6.5c-5 0-7 11-12 11C2.962 17.5.5 15.037.5 12S3 6.5 6 6.5s4.5 3.5 4.5 3.5"/>
    </svg>
  </div>
  <div class="read-next-card-content">
    <ul>
      
      
      
      <li>
        <a href="/2018/08/26/what-is-istio/">什么是 istio</a>
      </li>
      
      
      
      <li>
        <a href="/2018/08/25/knative-serverless-platform/">serverless 平台 knative 简介</a>
      </li>
      
      
      
      <li>
        <a href="/2018/06/25/kubernetes-resource-management/">kubernetes 资源管理概述</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/24/use-prometheus-and-grafana-to-monitor-linux-machine/">使用 promethues 和 grafana 监控自己的 linux 机器</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/13/linux-udp-packet-drop-debug/">linux 系统 UDP 丢包问题分析思路</a>
      </li>
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    </ul>
  </div>
  <footer class="read-next-card-footer">
    <a href="/archives">  MORE  → </a>
  </footer>
</article>


            
            
            
        </div>
    </div>
</aside>


<footer class="site-footer outer">

	<div class="site-footer-content inner">
		<section class="copyright">
			<a href="/" title="Cizixs Write Here">Cizixs Write Here</a>
			&copy; 2019
		</section>
		<nav class="site-footer-nav">
			
            <a href="https://hexo.io" title="Hexo" target="_blank" rel="noopener">Hexo</a>
            <a href="https://github.com/xzhih/hexo-theme-casper" title="Casper" target="_blank" rel="noopener">Casper</a>
        </nav>
    </div>
</footer>






<div class="floating-header" >
	<div class="floating-header-logo">
        <a href="/" title="Cizixs Write Here">
			
                <img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg" alt="Cizixs Write Here icon" />
			
            <span>Cizixs Write Here</span>
        </a>
    </div>
    <span class="floating-header-divider">&mdash;</span>
    <div class="floating-header-title">kubelet 源码分析：启动流程</div>
    <progress class="progress" value="0">
        <div class="progress-container">
            <span class="progress-bar"></span>
        </div>
    </progress>
</div>
<script>
   $(document).ready(function () {
    var progressBar = document.querySelector('progress');
    var header = document.querySelector('.floating-header');
    var title = document.querySelector('.post-full-title');
    var lastScrollY = window.scrollY;
    var lastWindowHeight = window.innerHeight;
    var lastDocumentHeight = $(document).height();
    var ticking = false;

    function onScroll() {
        lastScrollY = window.scrollY;
        requestTick();
    }
    function requestTick() {
        if (!ticking) {
            requestAnimationFrame(update);
        }
        ticking = true;
    }
    function update() {
        var rect = title.getBoundingClientRect();
        var trigger = rect.top + window.scrollY;
        var triggerOffset = title.offsetHeight + 35;
        var progressMax = lastDocumentHeight - lastWindowHeight;
            // show/hide floating header
            if (lastScrollY >= trigger + triggerOffset) {
                header.classList.add('floating-active');
            } else {
                header.classList.remove('floating-active');
            }
            progressBar.setAttribute('max', progressMax);
            progressBar.setAttribute('value', lastScrollY);
            ticking = false;
        }

        window.addEventListener('scroll', onScroll, {passive: true});
        update();

        // TOC
        var width = $('.toc-main').width();
        $('.toc-control').click(function () {
            if ($('.t-g-control').css('width')=="50px") {
                if ($('.t-g-control').css('right')=="0px") {
                    $('.t-g-control').animate({right: width}, "slow");
                    $('.toc-main').animate({right: 0}, "slow");
                    toc_icon()
                } else {
                    $('.t-g-control').animate({right: 0}, "slow");
                    $('.toc-main').animate({right: -width}, "slow");
                    toc_icon()
                }
            } else {
                if ($('.toc-main').css('right')=="0px") {
                    $('.toc-main').slideToggle("fast", toc_icon());
                } else {
                    $('.toc-main').css('right', '0px');
                    toc_icon()
                }
            }
        })

        function toc_icon() {
            if ($('.toc-icon').css('display')=="none") {
                $('.toc-close').hide();
                $('.toc-icon').show();
            } else {
                $('.toc-icon').hide();
                $('.toc-close').show();
            }
        }

        $('.gotop').click(function(){
            $('html,body').animate({scrollTop:$('.post-full-header').offset().top}, 800);
        });
        $('.gobottom').click(function () {
            $('html,body').animate({scrollTop:$('.pagination').offset().top}, 800);
        });

        // highlight
        // https://highlightjs.org
        $('pre code').each(function(i, block) {
            hljs.highlightBlock(block);
        });
        $('td.code').each(function(i, block) {
            hljs.highlightBlock(block);
        });

        console.log("this theme is from https://github.com/xzhih/hexo-theme-casper")
    });
</script>



<link rel="stylesheet" href="https://cdn.staticfile.org/lightgallery/1.3.9/css/lightgallery.min.css">



<script src="https://cdn.staticfile.org/lightgallery/1.3.9/js/lightgallery.min.js"></script>


<script>
	$(function () {
		var postImg = $('#lightgallery').find('img');
		postImg.addClass('post-img');
		postImg.each(function () {
			var imgSrc = $(this).attr('src');
			$(this).attr('data-src', imgSrc);
		});
		$('#lightgallery').lightGallery({selector: '.post-img'});
	});
</script>



<script>

/**
*  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
*  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/

var disqus_config = function () {
this.page.url = 'http://cizixs.com/2017/06/06/kubelet-source-code-analysis-part-1/';  // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = 'http://cizixs.com/2017/06/06/kubelet-source-code-analysis-part-1/'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};

(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://cizixs.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
                            


    </div>
</body>
</html>
